package nl.cypherpunk.statefuzzer.fuzzing;

import net.automatalib.words.Word;

import java.util.*;

public class FuzzingState {
    private String stateName;
    Random  rand;
    ArrayList<List<byte[]>> accessMessage;
    ArrayList<Word<String>> accessSymbol;
    public ArrayList<Double> accessScore;
    ArrayList<byte[]> seed;
    public ArrayList<Double> seedScore;
    public int fuzzs;
    public double score;
    public int coverageAdd;
    public FuzzingState(String state){
        stateName = state;
        rand = new Random();
        fuzzs = 0;
        score = 10.0;
        coverageAdd = 0;
        accessMessage = new ArrayList<>();
        accessSymbol = new ArrayList<>();
        accessScore = new ArrayList<>();
        seed = new ArrayList<>();
        seedScore = new ArrayList<>();
    }

    public void addState(List<byte[]> messages, Word<String> symbols){
        accessMessage.add(messages);
        accessSymbol.add(symbols);
        accessScore.add(10.0);
        score += 10.0;
    }

    public void addSeed(byte[] message){
        seed.add(message);
        seedScore.add(10.0);
    }

    public String getStateName(){
        return stateName;
    }

    public List<byte[]> getMessages(int index){
        return accessMessage.get(index);
    }

    public Word<String> getSymbols(int index){
        return accessSymbol.get(index);
    }

    public List<byte[]> getRandomMessages(){
        int index = getRandomIndex(accessScore);
        return accessMessage.get(index);
    }

    public Integer getRandomIndex(ArrayList<Double> map){
        NavigableMap<Double, Integer> hashMap = new TreeMap<>();
        double total = 0;
        for (int i = 0; i < map.size(); i++) {
            total += map.get(i);
            hashMap.put(total, i);
        }
        Double weight = 1.0 * rand.nextInt((int) total);
        return hashMap.ceilingEntry(weight).getValue();
    }

    public void addAccessScore(int index, double score){
        accessScore.set(index,accessScore.get(index)+score);
    }

    public void addSeedScore(int index, double score){
        seedScore.set(index,accessScore.get(index)+score);
    }


}
